
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "singly-linked-list.h"

int InitList(SinList *List){
    List->list_head = NULL;
    List->list_length = 0;
    return(0);
}

int ListEmpty(SinList List){
    if (List.list_length == 0 && List.list_head == NULL){
        return(1);
    } else if (List.list_length == 0 || List.list_head == NULL){
        return(-1);
    }else{
        return(0);
    }
}

int ClearList(SinList *List){
    SinLiNode *p_current = List->list_head;
    while (p_current){
        SinLiNode *p_next = p_current->next_node;
        free(p_current);
        p_current = p_next;
        --List->list_length;
    }
    List->list_head = NULL;
    return((int)List->list_length);
}

int GetElem(SinList List,unsigned int i,ElemType *e){
    if (List.list_head == NULL || List.list_length == 0){
        return(-1);
    } else if(i == 0 || i > List.list_length){
        return(EDOM);
    } else{
        SinLiNode *p_current = List.list_head;
        for (int j = 1; j < i; ++j) {
            p_current = p_current->next_node;
        }
        memcpy(e,&p_current->node_data, sizeof(ElemType));
        return(0);
    }
}

int LocateElem(SinList List,ElemType e){
    unsigned int e_location = 0;
    if (List.list_head == NULL || List.list_length == 0){
        return(-1);
    }else{
        SinLiNode *p_current = List.list_head;
        while (p_current){
            ++e_location;
            if(memcmp(&p_current->node_data,&e, sizeof(ElemType)) == 0){
                return((int)e_location);
            }
            p_current = p_current->next_node;
        }
        return(0);
    }
}

int ListInsert(SinList *List,unsigned int i,ElemType e){
    SinLiNode *p_current = List->list_head;
    if (i == 0){
        return(-1);
    }else if (i == 1){
        List->list_head = malloc(sizeof(SinLiNode));
        List->list_head->next_node = p_current;
        memcpy(&List->list_head->node_data,&e, sizeof(ElemType));
        List->list_head->next_node = NULL;
        ++List->list_length;
        return(0);
    }else if(List->list_head == NULL && List->list_length == 0){
        List->list_head = malloc(sizeof(SinLiNode));
        p_current = List->list_head;
        memset(&p_current->node_data,0, sizeof(ElemType));
        ++List->list_length;
        for (int j = 1; j < i; ++j) {
            p_current->next_node = malloc(sizeof(SinLiNode));
            p_current = p_current->next_node;
            memset(&p_current->node_data,0, sizeof(ElemType));
            ++List->list_length;
        }
        p_current->next_node = NULL;
        memcpy(&p_current->node_data,&e,sizeof(ElemType));
        return(0);
    }else if (List->list_head == NULL || List->list_length == 0){
        return(-2);
    }else{
        for (int j = 2; j < i; ++j) {
            if (p_current->next_node == NULL){
                p_current->next_node = malloc(sizeof(SinLiNode));
                p_current->next_node->next_node = NULL;
                memset(&p_current->next_node->node_data,0, sizeof(ElemType));
                ++List->list_length;
            }
            p_current = p_current->next_node;
        }
        SinLiNode *p_tmp = p_current->next_node;
        p_current->next_node = malloc(sizeof(SinLiNode));
        p_current = p_current->next_node;
        p_current->next_node = p_tmp;
        memcpy(&p_current->node_data,&e, sizeof(ElemType));
        ++List->list_length;
        return(0);
    }
}

int ListDelete(SinList *List,unsigned int i,ElemType *e){
    SinLiNode *p1,*p2;
    if (List == NULL ||
        List->list_head ==NULL ||
        List->list_length == 0 ||
        i == 0 ||
        i > List->list_length)
    {
        return(-1);
    }else if (i == 1){
        p1 = List->list_head;
        p2 = p1->next_node;
        memcpy(e,&p1->node_data, sizeof(ElemType));
        free(p1);
        List->list_head = p2;
        --List->list_length;
        return(0);
    }else{
        p1 = List->list_head;
        p2 = p1->next_node;
        for (int j = 2; j < i; ++j) {
            p1 = p1->next_node;
            p2 = p2->next_node;
        }
        p1->next_node = p2->next_node;
        memcpy(e,&p2->node_data, sizeof(ElemType));
        free(p2);
        --List->list_length;
        return(0);
    }
}